#ifndef LAURIN_IEEE80211_H_
#define LAURIN_IEEE80211_H_

#include "laurin-utils.h" // for ETH_ALEN
#include <sys/types.h>


// some code is from ieee80211.h
// copyrights holds.
// code is repeated for not assuming a specific kernel configuration.

/*
 802.11 data frame from AP

      ,-------------------------------------------------------------------.
Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
      |------|------|---------|---------|---------|------|---------|------|
Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  frame  |  fcs |
      |      | tion | (BSSID) |         |         | ence |  data   |      |
      `-------------------------------------------------------------------'

Total: 28-2340 bytes

*/

/* Frame control field constants */
#define IEEE80211_FCTL_VERS             0x0003		/* version */
#define IEEE80211_FCTL_FTYPE            0x000c		/* type */
#define IEEE80211_FCTL_STYPE            0x00f0		/* subtype */
#define IEEE80211_FCTL_TODS             0x0100		/* to ds */
#define IEEE80211_FCTL_FROMDS           0x0200		/* from ds */
#define IEEE80211_FCTL_MOREFRAGS        0x0400		/* more fragments remains?*/
#define IEEE80211_FCTL_RETRY            0x0800		/* retry */
#define IEEE80211_FCTL_PM               0x1000		/* power management */
#define IEEE80211_FCTL_MOREDATA         0x2000		/* AP has more buffered frame for STA */
#define IEEE80211_FCTL_PROTECTED        0x4000		/* crypted? */
#define IEEE80211_FCTL_ORDER            0x8000		/* sta requires frames to be delivered in order */

/* frame type */
#define IEEE80211_FTYPE_MGMT            0x0000		/* management frame */
#define IEEE80211_FTYPE_CTL             0x0004		/* control frame */
#define IEEE80211_FTYPE_DATA            0x0008		/* data frame */

/* management subtype */
#define IEEE80211_STYPE_ASSOC_REQ       0x0000		/* association request */
#define IEEE80211_STYPE_ASSOC_RESP      0x0010		/* association response */
#define IEEE80211_STYPE_REASSOC_REQ     0x0020		/* reassociation request */
#define IEEE80211_STYPE_REASSOC_RESP    0x0030		/* reassociation response */
#define IEEE80211_STYPE_PROBE_REQ       0x0040		/* probe request */
#define IEEE80211_STYPE_PROBE_RESP      0x0050		/* probe response */
#define IEEE80211_STYPE_BEACON          0x0080		/* beacon */
#define IEEE80211_STYPE_ATIM            0x0090		/* announcement traffic indication map (ATIM) */
#define IEEE80211_STYPE_DISASSOC        0x00A0		/* disassociate */
#define IEEE80211_STYPE_AUTH            0x00B0		/* authentication */
#define IEEE80211_STYPE_DEAUTH          0x00C0		/* deauthentication */
#define IEEE80211_STYPE_ACTION          0x00D0		/* action frame */

/* control subtype */
#define IEEE80211_STYPE_PSPOLL          0x00A0		/* power-save poll */
#define IEEE80211_STYPE_RTS             0x00B0		/* request to send*/
#define IEEE80211_STYPE_CTS             0x00C0		/* clear to send */
#define IEEE80211_STYPE_ACK             0x00D0		/* ack */
#define IEEE80211_STYPE_CFEND           0x00E0		/* content free period end */
#define IEEE80211_STYPE_CFENDACK        0x00F0		/* content free period end ack */

/* data subtype */
#define IEEE80211_STYPE_DATA            0x0000		/* data */
#define IEEE80211_STYPE_DATA_CFACK      0x0010		/* data + content free ack */
#define IEEE80211_STYPE_DATA_CFPOLL     0x0020		/* data + content free poll */
#define IEEE80211_STYPE_DATA_CFACKPOLL  0x0030		/* data + content free ack + content free poll */
#define IEEE80211_STYPE_NULLFUNC        0x0040		/* null data */
#define IEEE80211_STYPE_CFACK           0x0050		/* content free ack */
#define IEEE80211_STYPE_CFPOLL          0x0060		/* content free poll */
#define IEEE80211_STYPE_CFACKPOLL       0x0070		/* content free ack + poll */
#define IEEE80211_STYPE_QOS_DATA        0x0080		/* qos data */


#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS)		/* get protocol version - always 0*/
#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)		/* get frame type */
#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)		/* get frame subtype */
#define WLAN_FC_GET_FROMDS(fc) ((fc) & IEEE80211_FCTL_FROMDS)	/* get from ds bit value */
#define WLAN_FC_GET_TODS(fc) ((fc) & IEEE80211_FCTL_TODS)		/* get to ds bit value */


#define IEEE80211_3ADDR_LEN 24
#define IEEE80211_TAGGED_PARAMETERS_OFFSET 36



// from this we can get the right header checking the frame_ctl fields.
struct laurin_ieee80211_hdr {
	u_int16_t frame_ctl;
	u_int16_t duration_id;
	u_int8_t payload[0];
} __attribute__((packed));


struct laurin_ieee80211_hdr_3addr {
	u_int16_t frame_ctl;
	u_int16_t duration_id;
	u_int8_t addr1[ETH_ALEN];
	u_int8_t addr2[ETH_ALEN];
	u_int8_t addr3[ETH_ALEN];
	u_int16_t seq_ctl;
	u_int8_t payload[0];
} __attribute__((packed));


#endif
